package com.kun.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.kun.constant.SecurityConstant;
import com.kun.entity.SysPermission;
import com.kun.entity.SysTenant;
import com.kun.entity.SysUser;
import com.kun.remote.RemoteTenantService;
import com.kun.remote.RemoteUserService;
import com.kun.util.BuildKeyUtil;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kun.li
 */
public class LoginUserDetailService implements UserDetailsService {
    @Resource
    private RemoteUserService remoteUserService;

    @Resource
    private RemoteTenantService remoteTenantService;


    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StrUtil.isEmpty(username)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        String[] splitUserInfo = username.split(":");
        String name = splitUserInfo[0];
        String tenantId;
        if (splitUserInfo.length > 1) {
            tenantId = splitUserInfo[1];
        } else {
            tenantId = SecurityConstant.DEFAULT_TENANT;
            username = name + ":" + tenantId;
        }
        SysTenant sysTenant = remoteTenantService.getSysTenant(tenantId);

        Date expireTime = sysTenant.getExpireTime();
        if (ObjectUtil.isNotNull(expireTime)) {
            if (DateUtil.current() > expireTime.getTime()) {
                throw new RuntimeException("租户套餐已经到期");
            }
        }
        // 缓存用户信息
        KunUser userInfo = (KunUser) redisTemplate.opsForValue().get(username);
        if (userInfo != null) {
            return userInfo;
        }
        SysUser sysUser = remoteUserService.getSysUser(tenantId, name, null);
        if (ObjectUtil.isNull(sysUser)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 查看用户对应菜单权限 /api/**  admin
        List<SysPermission> sysPermissions = remoteUserService.selectPermission(tenantId, sysUser.getUserId());
        Set<GrantedAuthority> roleSet = new HashSet<>();
        List<String> urlPer = new ArrayList<>();
        for (SysPermission sysPermission : sysPermissions) {
            String methodType = sysPermission.getMethodType();
            String urlPermission = sysPermission.getUrlPermission();
            if (StrUtil.isEmpty(urlPermission)) {
                continue;
            }
            urlPer.add(methodType + urlPermission);
            roleSet.add(new SimpleGrantedAuthority(sysPermission.getRoleCode()));
        }
        // mapping URL->[admin,test]
        String roleGroup = roleSet.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));
        for (String url : urlPer) {
            redisTemplate.opsForHash().put(BuildKeyUtil.buildKey(username), url, roleGroup);
        }
        KunUser userDetails = new KunUser(sysUser.getUsername(), sysUser.getPassword(),
                sysUser.getUserId(), sysUser.getTenantId(), sysUser.getHasAdmin(), roleSet);
        redisTemplate.opsForValue().set(username, userDetails);
        return userDetails;
    }
}
